package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.ZsyyCollectFees;
import com.ruoyi.system.dto.CollectTimeFeeCeshiBo;
import com.ruoyi.system.mapper.ZsyyCollectFeesMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.bo.ZsyyCollectTimeAddBo;
import com.ruoyi.system.bo.ZsyyCollectTimeQueryBo;
import com.ruoyi.system.bo.ZsyyCollectTimeEditBo;
import com.ruoyi.system.domain.ZsyyCollectTime;
import com.ruoyi.system.mapper.ZsyyCollectTimeMapper;
import com.ruoyi.system.vo.ZsyyCollectTimeVo;
import com.ruoyi.system.service.IZsyyCollectTimeService;
import com.ruoyi.system.mapper.ZsyyCollectTimeMapper;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 计费规则时段Service业务层处理
 *
 * @author wangghua
 * @date 2021-07-14
 */
@Service
public class ZsyyCollectTimeServiceImpl extends ServicePlusImpl<ZsyyCollectTimeMapper, ZsyyCollectTime> implements IZsyyCollectTimeService {
    @Autowired
    private ZsyyCollectTimeMapper iZsyyCollectTimeMapper;
    @Autowired
    private ZsyyCollectFeesMapper collectFeesMapper;

    @Override
    public ZsyyCollectTimeVo queryById(Long id){
        return getVoById(id, ZsyyCollectTimeVo.class);
    }

    @Override
    public TableDataInfo<ZsyyCollectTimeVo> queryPageList(ZsyyCollectTimeQueryBo bo) {
		Page<ZsyyCollectTimeVo> result = iZsyyCollectTimeMapper.queryPageList(PageUtils.buildPage(),bo);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<ZsyyCollectTimeVo> queryList(ZsyyCollectTimeQueryBo bo) {
        return listVo(buildQueryWrapper(bo), ZsyyCollectTimeVo.class);
    }

    private LambdaQueryWrapper<ZsyyCollectTime> buildQueryWrapper(ZsyyCollectTimeQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZsyyCollectTime> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getFeesId() != null, ZsyyCollectTime::getFeesId, bo.getFeesId());
        return lqw;
    }

    @Override
    public Boolean insertByAddBo(ZsyyCollectTimeAddBo bo) {
		bo.setSubmitName(SecurityUtils.getUsername());
        ZsyyCollectTime add = BeanUtil.toBean(bo, ZsyyCollectTime.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(ZsyyCollectTimeEditBo bo) {
		bo.setSubmitName(SecurityUtils.getUsername());
        ZsyyCollectTime update = BeanUtil.toBean(bo, ZsyyCollectTime.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(ZsyyCollectTime entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    /**
     * @Author wangghua
     * @Description 费用测算
     * @Date 16:09 2021/8/20
     * @Param [bo]
     * @return java.lang.String
     **/
	@Override
	public String ceshiCollectTime(CollectTimeFeeCeshiBo bo) {
		try {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//注意月份是MM
			Date startDate = simpleDateFormat.parse(bo.getStartTime());
			Date endDate = simpleDateFormat.parse(bo.getEndTime());
			return quotaCharge1(startDate,endDate,bo.getFeesId());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return "0";
	}



	/*计算收费规则*/
	public String quotaCharge1(Date startTime,Date endTime,Long feesId) {
		SimpleDateFormat sim = new SimpleDateFormat("HH:mm:ss");
		ZsyyCollectFees collectFees = collectFeesMapper.selectById(feesId);
		if (collectFees == null) {
			return "0";
		}
		//免费时长
		int freeTime = collectFees.getFreeTime()*60;
		String hhmmssStart = sim.format(startTime);
		int startTimeSs1 = this.getTimeSs(hhmmssStart,0);
		int startTimeSs2 = this.getTimeSs(hhmmssStart,1);
		int startTimeSs = -1;
		//总时长
		int totalTimeSs = (int)((endTime.getTime()-startTime.getTime())/1000);
		int subTimeSs = 0;//已计算的时间
		if(totalTimeSs<=freeTime){
			//在免费时长段内
			return "0";
		}
		if(collectFees.getCharging()==1){
			//免费时长不列入计费，那么得把这段时间剔除
			totalTimeSs -= freeTime;
			startTimeSs1+=freeTime;
			startTimeSs2+=freeTime;

		}
		List<ZsyyCollectTime> collectTimes = iZsyyCollectTimeMapper.selectByFeesId(feesId);

		for (ZsyyCollectTime collectTime:collectTimes
		) {
			String[] timeSlot = collectTime.getTimeSlot().split("-");
			int startTimeSsT = this.getTimeSs(timeSlot[0],0);
			int endTimeSsT = this.getTimeSs(timeSlot[1],0);
			if(endTimeSsT<=startTimeSsT){
				endTimeSsT = this.getTimeSs(timeSlot[1],1);
			}
			int totalTimeSsT = endTimeSsT-startTimeSsT;
			int maxFree = 0;
//            type收费方式（0 按次定额收费，1 按单价收费，2 递增收费）
//            settlement结算方式（0 自然结算，1 强制结算，2 封顶结算,3定额交费）
			if(collectTime.getType()==1&&collectTime.getSettlement()==2){
				maxFree = (int)(new BigDecimal(collectTime.getFendingPrice()).floatValue()*100);
			}else if(collectTime.getType()==1) {
				int slotNum = 0;
				int slotTotalTime = endTimeSsT - startTimeSsT;
				int slotTime = collectTime.getMinute() * 60;
				int slotFree = (int) (new BigDecimal(collectTime.getPrice()).floatValue() * 100);
				if (totalTimeSs % slotTime == 0) {
					//刚好整除
					slotNum = totalTimeSs / slotTime;
				} else {
					//不整除加1
					slotNum = totalTimeSs / slotTime + 1;
				}

				maxFree = slotNum * slotFree;
			}else if(collectTime.getType()==0){
				maxFree = (int) (new BigDecimal(collectTime.getPrice()).floatValue() * 100);
			}

			collectTime.setStartTimeSs(startTimeSsT);
			collectTime.setEndTimeSs(endTimeSsT);
			collectTime.setTotalTimeSs(totalTimeSsT);
			collectTime.setMaxFree(maxFree);

		}


		BigDecimal bigDecimal = new BigDecimal(0);
		int totalFree = 0;
		int hourSub = 0;//不是整小时的时间差
		for (int i = 0;i<1000;i++){
			for (ZsyyCollectTime collectTime:collectTimes
			) {
				if(startTimeSs==-1){
					if(startTimeSs1>=collectTime.getStartTimeSs()&&startTimeSs1<collectTime.getEndTimeSs()){
						startTimeSs = startTimeSs1;
					}

					if(startTimeSs2>=collectTime.getStartTimeSs()&&startTimeSs2<collectTime.getEndTimeSs()){
						startTimeSs = startTimeSs2;
					}
				}
				if(i>0&&startTimeSs==-1){
					//计费时间段，错误
					return "0";
				}
				//开始用规则计费

				//规则时间
				int slotTime = collectTime.getMinute()*60;
				//规则费用
				int slotFree = (int)(new BigDecimal(collectTime.getPrice()).floatValue()*100);
				int maxFree = collectTime.getMaxFree();

//            type收费方式（0 按次定额收费，1 按单价收费，2 递增收费）
//            settlement结算方式（0 自然结算，1 强制结算，2 封顶结算,3定额交费）
				if(startTimeSs!=-1){
					if(subTimeSs>0){
						startTimeSs = collectTime.getStartTimeSs();
					}
					startTimeSs+=hourSub;

					int tempTime = collectTime.getEndTimeSs()-startTimeSs;//得到当前计费时间段到结束的秒数
					int nowTimeSs = totalTimeSs-subTimeSs;

					if(tempTime>=nowTimeSs){
						tempTime = nowTimeSs;
					}else if(tempTime%slotTime!=0){
						//测算不是整规则的情况

						//差整规则多少秒
						hourSub =slotTime - tempTime%slotTime;

					}

					if(collectTime.getType()==1){
						//按单价收费
						int slotNum = 0;
						if(tempTime%slotTime==0){
							//刚好整除
							slotNum = tempTime/slotTime;
						}else {
							//不整除加1
							slotNum = tempTime/slotTime+1;
						}
						int slotTotalFree = slotNum*slotFree;
						if(slotTotalFree>maxFree){
							totalFree+= maxFree;
							hourSub = 0;//价格已超出上线，不需要补不是整规则的差]
						}else {
							totalFree+= slotTotalFree;
							//不是整规则也没有超出封顶费用得把时间补上
							tempTime+=hourSub;
						}
					}else if(collectTime.getType()==0){
						//按次数收费
						totalFree+= maxFree;
					}

					//说明是最后一段
					if(tempTime>=nowTimeSs){
						return totalFree/100f+"";
					}


					subTimeSs+=tempTime;

				}


			}
		}

		return "0";

	}

	//计算两个时间相差天数
	public  static int differentDayMillisecond (Date date1, Date date2){
		int day = (int)((date2.getTime()-date1.getTime())/(3600*1000*24));
		return day;
	}

	//按单价收费计算价格
	public static BigDecimal getDJPrice(long timeMinute, ZsyyCollectTime coll){
		BigDecimal big = new BigDecimal(timeMinute);
		BigDecimal multiply = big.divide(new BigDecimal(coll.getMinute()), 2).multiply(new BigDecimal(coll.getPrice()));
		return multiply;
	}

	//递增收费计算价格
	public static BigDecimal getDZPrice(long timeMinute,ZsyyCollectTime coll){
		if(timeMinute<=coll.getMinute()){
			BigDecimal big = new BigDecimal(timeMinute);
			return big.divide(new BigDecimal(coll.getMinute()), 2).multiply(new BigDecimal(coll.getPrice()));
		}else {
			BigDecimal big = new BigDecimal(timeMinute-coll.getMinute());
			BigDecimal multiply = big.divide(new BigDecimal(coll.getLastMinute()), 2).multiply(new BigDecimal(coll.getLastPrice()));
			return multiply.add(new BigDecimal(coll.getPrice()));
		}

	}

	//判断价格是否高于封顶价格
	public static BigDecimal getPrice(BigDecimal price,String fendingPrice){
		double newPrice = price.doubleValue();
		double newFending = Double.parseDouble(fendingPrice);
		if(newPrice-newFending<0){
			return price;
		}else {
			return new BigDecimal(fendingPrice);
		}
	}

	//时间是否是整小时
	public static BigDecimal getTimeHour(long time){
		BigDecimal big = null;
		if(time%60==0){
			big = new BigDecimal(time);
		}else {
			big = new BigDecimal((time/60+1)*60);
		}
		return big;
	}

	//计算时间段与时段相差(分钟)
	public static long getTimeMinute(Date time,Date slotTime){
		long time1 =time.getTime();
		long time2 = slotTime.getTime();
		long timeLongth=(time2-time1)/1000/60;
		return Math.abs(timeLongth) ;
	}

	//拼接时间
	public static Date getTimeSplicing(Date time,String slotTime){
		int sy = time.getYear()+1900;
		int sm = time.getMonth()+1;
		int sd = time.getDate();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		Date newTime = null;
		try {
			newTime = format.parse(sy+"-"+sm+"-"+sd+" "+slotTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return newTime ;
	}

	//判断进出场时间是否大于免费时长
	public static boolean isFree(Date startTime,Date endTime,Integer isTime){
		BigDecimal bigDecimal = new BigDecimal(isTime.toString()).
			divide(new BigDecimal(60),2).
			multiply(new BigDecimal(3600000));
		Long freeTime = bigDecimal.longValue();
		Long time = endTime.getTime()-startTime.getTime();
		if(time>freeTime)
			return true;
		else
			return false;
	}

	//切割时间段
	public static String[] spiltTime(String sTime,String eTime){
		String[] newTime1 = sTime.split(":");
		String[] newTime2 = eTime.split(":");
		String[] time = new String[4];
		if(Integer.parseInt(newTime2[0])-Integer.parseInt(newTime1[0])<0){
			time[0] = sTime;
			time[1] = "23:59:59";
			time[2] = "1:00:00";
			time[3] = eTime;
		}else {
			time[0] = sTime;
			time[1] = eTime;
			time[2] = "00:00:00";
			time[3] = "00:00:00";
		}
		return time;
	}

	//判断是否大于24小时
	public static boolean isExceed(Date startTime,Date endTime){
		Long freeTime = 86400000L;
		Long time = endTime.getTime()-startTime.getTime();
		if(time>freeTime)
			return true;
		else
			return false;
	}

	//获取时间年月日时分
	public static int[] getBurstTime(Date time){
		int sy = time.getYear()+1900;
		int sm = time.getMonth()+1;
		int sd = time.getDate();
		int sh = time.getHours();
		int smu = time.getMinutes();
		int[] times = new int[5];
		times[0] = sy;
		times[1] = sm;
		times[2] = sd;
		times[3] = sh;
		times[4] = smu;
		return times;
	}


	//计算时间段的时长(分钟)
	public static long getTimeLength(Date startTime,Date endTime){
		long time1 =startTime.getTime();
		//从对象中拿到时间
		long time2 = endTime.getTime();
		long timeLongth=(time2-time1)/1000/60;
		return timeLongth;
	}

	//判断时间属于那个区间(1 规则之前，2 规则之中，3 规则之后)
	public static int getTimeSection(String[] times,int ysTime,int ynTime){
		String[] spit1 = times[0].split(":");
		String[] spit2 = times[1].split(":");
		String[] spit3 = times[2].split(":");
		String[] spit4 = times[3].split(":");
		if(
			(ysTime<Integer.parseInt(spit1[0])&&ynTime<=Integer.parseInt(spit2[0]))&&
				(ynTime<=Integer.parseInt(spit4[0]))
		){
			return 1;
		}else if(
			(ysTime>=Integer.parseInt(spit1[0])&&ynTime<=Integer.parseInt(spit2[0]))||
				(ysTime>=Integer.parseInt(spit3[0])&&ynTime<=Integer.parseInt(spit4[0]))
		){
			return 2;
		}else if(
			(ysTime<Integer.parseInt(spit1[0])&&ynTime<=Integer.parseInt(spit2[0]))&&
				(ynTime<=Integer.parseInt(spit4[0]))
		){
			return 3;
		}
		return 0;
	}

	//获取时间所在当天的秒,day 0当天，为1加一天
	public int getTimeSs(String hhmmss,int day){
		hhmmss = hhmmss.replace(" ","");
		String[] times = hhmmss.split(":");
		int time = 0;
		for (int i=0; i<3;i++){
			if(i==0){
				//时
				time+=Integer.parseInt(times[i])*60*60;
			}else  if(i==1){
//                分
				time+=Integer.parseInt(times[i])*60;
			} if(i==2){
//                秒
				time+=Integer.parseInt(times[i]);
			}
		}
		if(day==1){
			time+= 60*60*24;
		}
		return time;
	}

}
